﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Windows.Threading;

using AForge.Imaging;
using AForge.Imaging.Filters;
using AForge.Math;

using Image = System.Drawing.Image;
using System.Drawing.Imaging; //Remove ambiguousness between AForge.Image and System.Drawing.Image

namespace ChessOnlineTool
{
    public partial class Form1 : Form
    {

        private Bitmap img;
        private Timer t = new Timer();
        private Rectangle region;

        public string[] symbol = new string[] { "wk", "wq", "wr", "wb", "wn", "wp", "bk", "bq", "br", "bb", "bn", "bp" };
        public Dictionary<string, Bitmap> Pics = new Dictionary<string, Bitmap>();

        private ChessEngine engine;
        private string best = "e2e4";
        public Form1()
        {
            InitializeComponent();
            this.Paint += new PaintEventHandler(Form1_Paint);
            this.Location = new Point(Screen.PrimaryScreen.Bounds.Width / 2, 0);

            Rectangle huupc = new Rectangle(43, 370, 484, 484);
            Rectangle nganpc = new Rectangle(43, 180, 484, 484);
            Rectangle chesscom = new Rectangle(60, 150, 484, 484);
            region = chesscom;

            foreach (string s in symbol)
            {
                Bitmap tmp = (Bitmap)Image.FromFile("Image\\" + s + ".bmp");
                Pics.Add(s, tmp);
            }

            img = new Bitmap(region.Width, region.Height, PixelFormat.Format24bppRgb);
            this.Width = region.Width + 15;
            //this.Height = region.Height+ 36;

            t.Interval = 100;
            t.Tick += new EventHandler(t_Tick);
            t.Start();

            engine = new ChessEngine("Engine\\houdini.exe");
            engine.Proc.OutputDataReceived += Proc_OutputDataReceived;
        }

        void t_Tick(object sender, EventArgs e)
        {
            Graphics g = Graphics.FromImage(img);
            g.CopyFromScreen(region.X, region.Y, 0, 0, region.Size, CopyPixelOperation.SourceCopy);
            Refresh();
        }

        void Form1_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.DrawImage(img, 0, 0, region.Width, region.Height);
            if (best != "")
            { 
                //Draw arrow
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            best = "";
            SendFen(GetFenString(), "depth 10");
        }

        private string GetFenString()
        {
            Bitmap temp = img.Clone() as Bitmap;

            FiltersSequence seq = new FiltersSequence();
            seq.Add(Grayscale.CommonAlgorithms.BT709);  //First add  GrayScaling filter
            seq.Add(new Threshold(50)); //Then add binarization(thresholding) filter

            temp = seq.Apply(img);
            ExhaustiveTemplateMatching tm = new ExhaustiveTemplateMatching(0.9f);

            string str = "";
            for (int i = 0; i < 8; i++)
            {
                string row = "";
                int countblank = 0;
                for (int j = 0; j < 8; j++)
                {
                    Rectangle rect = new Rectangle(2 + j * 60, 2 + i * 60, 60, 60);
                    Bitmap tmp = temp.Clone(rect, PixelFormat.DontCare);
                    tmp.Save("Image\\" + i + "x" + j + ".bmp");
                    ImageStatistics stat = new ImageStatistics(tmp);

                    int black = stat.PixelsCount - stat.PixelsCountWithoutBlack;
                    if (black > 100)
                    {

                        foreach (KeyValuePair<string, Bitmap> p in Pics)
                        {
                            TemplateMatch[] matches = tm.ProcessImage(tmp, p.Value);
                            if (matches.Length > 0)
                            {
                                string k = "";
                                switch (p.Key)
                                {
                                    case "wr": k = "R"; break;
                                    case "wb": k = "B"; break;
                                    case "wn": k = "N"; break;
                                    case "wk": k = "K"; break;
                                    case "wq": k = "Q"; break;
                                    case "wp": k = "P"; break;
                                    case "br": k = "r"; break;
                                    case "bb": k = "b"; break;
                                    case "bn": k = "n"; break;
                                    case "bk": k = "k"; break;
                                    case "bq": k = "q"; break;
                                    case "bp": k = "p"; break;
                                    default: break;
                                }
                                row += (countblank == 0 ? "" : countblank.ToString()) + k;

                                countblank = 0;
                                break;
                            }
                        }

                    }
                    else countblank++;
                }
                str = str + (str == "" ? "" : "/") + row + (countblank == 0 ? "" : countblank.ToString());
            }

            if (radioButton3.Checked) str = new string(str.Reverse().ToArray());

            str += (radioButton1.Checked ? " w" : " b");

            string castle = "";
            if (checkBox1.Checked) castle += "K";
            if (checkBox2.Checked) castle += "Q";
            if (checkBox3.Checked) castle += "k";
            if (checkBox4.Checked) castle += "q";
            str += (castle == "" ? " -" : " " + castle);

            str += " - 0 10";

            return str;
        }

        private void button3_Click(object sender, EventArgs e)
        {

            engine.Start();
        }

        void Proc_OutputDataReceived(object sender, System.Diagnostics.DataReceivedEventArgs e)
        {
            if (e.Data != null && e.Data != "")
            {
                string line = e.Data.ToString().Trim();
                this.BeginInvoke(new Action(() => ParseOutput(line)), null);

            }
        }
        public void ParseOutput(string output)
        {
            textBox2.Text = output;
            char[] sep = new char[] { ' ' };
            string[] str = output.Split(sep);

            if (str[0] == "bestmove")
            {
                best = str[1];
            }
            //else textBox1.Text = output;
        }
        public void SendFen(string fen, string option)
        {
            textBox1.Text = fen;
            if (engine == null) return;
            engine.Proc.StandardInput.WriteLine("position fen " + fen);
            //engine.StandardInput.WriteLine("go depth " + Depth);
            engine.Proc.StandardInput.WriteLine("go " + option);
        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {

        }

        private void button2_Click(object sender, EventArgs e)
        {
            Bitmap temp = img.Clone() as Bitmap;

            FiltersSequence seq = new FiltersSequence();
            seq.Add(Grayscale.CommonAlgorithms.BT709);  //First add  GrayScaling filter
            seq.Add(new Threshold(50)); //Then add binarization(thresholding) filter

            temp = seq.Apply(img);

            for (int i = 0; i < 8; i++)
            {
                for (int j = 0; j < 8; j++)
                {
                    Rectangle rect = new Rectangle(2 + j * 60, 2 + i * 60, 60, 60);
                    Bitmap tmp = temp.Clone(rect, PixelFormat.DontCare);
                    tmp.Save("Image\\" + i + "x" + j + ".bmp");
                }
            }
        }

        private void groupBox2_Enter(object sender, EventArgs e)
        {

        }

        private void radioButton3_CheckedChanged(object sender, EventArgs e)
        {

        }

        private void button4_Click(object sender, EventArgs e)
        {

        }
    }
}
